www.gusucode.com > VC编写的串口调试软件 > VC编写的串口调试软件,内含Modbus协议类 支持对Modbus通讯调试/Modbus串口调试软件1.0/ModBus.cpp

    // ModBus.cpp: implementation of the CModBus class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ModBus.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: LRC------纵向异或校验
//----------------------------------------------------
//参数: const CString& strTxt-------------字符串
//----------------------------------------------------
//功能:纵向异或校验
//----------------------------------------------------
//返回值:
//	校验码(1个 char)
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
unsigned char CModBus::LRC(const unsigned char *pucChar, unsigned int unLen)
{
	//在ASCII协议中使用,检测了消息域中除开始的冒号及结束的回车换行号外的内容。
	//它仅仅是把每一个需要传输的数据按字节叠加后取反加1即可

	unsigned char ucLRC=0;

	if(0!=unLen%2)
		return 0;

	BYTE byLRC = 0; 
	char pBuf[4]; 
	pBuf [2] = '\0'; 

	int nData = 0; 
	for(unsigned int i=0; i<unLen; i+=2)	
	{ 
		//每两个需要发送的ASCII码转化为一个十六进制数 
		pBuf [0] = pucChar[i]; 
		pBuf [1] = pucChar[i+1]; 
//		pBuf [2] = '\0'; 
		sscanf(pBuf,"%x",& nData); 
		byLRC += nData; 
	} 
	byLRC = ~ byLRC; 
	byLRC ++; 
	return byLRC; 

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: CRC16------循环容余校验
//----------------------------------------------------
//参数: unsigned char *pucChar-------------接收到的字符
//----------------------------------------------------
//功能: 循环容余校验
//----------------------------------------------------
//返回值:
//	校验码	
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
unsigned short CModBus::CRC16(const unsigned char *pucChar, unsigned int unLen)
{
	unsigned short usItem=0xA001;
	unsigned short usCRCReg=0xFFFF;
	unsigned char  ucChar;
	for(unsigned int i=0;i<unLen;i++)
	{
		ucChar=*(pucChar+i);
		usCRCReg^=ucChar;
		for(int j=0;j<8;j++)
		{
			bool bLSB=((usCRCReg & 0x0001)== 0x0001);
			usCRCReg=usCRCReg>>1;
			if(bLSB)
			{
				usCRCReg^=usItem;
			}
		}
	}
	return usCRCReg;

//	unsigned char uchCRCHi=0xFF;
//	unsigned char uchCRCLo=0xFF;
//	unsigned uIndex;
//
//	while(unLen--)
//	{
//		uIndex=uchCRCLo^*pucChar++;			//calculate the CRC
//		uchCRCLo=uchCRCHi^auchCRCHi[uIndex];
//		uchCRCHi=auchCRCLo[uIndex];
//	}
//	return(uchCRCHi<<8|uchCRCLo);
}

//Table of CRC Value for high-order byte
//unsigned char CModBus::auchCRCHi[]={
//	1    2    3    4    5    6    7    8    9
//	0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01
//};

//Table of CRC value for low-order byte
//unsigned char CModBus::auchCRCLo[]={
//	0x00,0xC0,0xC1,0x01
//};

CModBus::CModBus()
{
	m_strPrtName="ModBus";

	m_unRLen=500;			//将要接收字符长度
	m_unNowRLen=0;			//已经接收字符长度

	m_bFrameMode=MODBUS_RTU;	//
}

CModBus::~CModBus()
{

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Error------错误提示
//----------------------------------------------------
//参数: int nError-------------错误代码
//      int nFunctionCode------功能代码
//		int nRegAddr-----------寄存器地址
//----------------------------------------------------
//功能: 错误代码提示
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Error(int nError,int nFunctionCode,int nRegAddr)
{
	CString strErrTip;
	switch(nError)
	{
	case 0x01:
		strErrTip.Format("从机接收到的功能是不允许的。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	case 0x02:
		strErrTip.Format("查询中的数据地址对于从机来说是非法的。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	case 0x03:
		strErrTip.Format("查询中数据域的数值不是从机所允许的。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	case 0x04:
		strErrTip.Format("当从机试图进行所要求的动作时,发生了一个不可恢复的错误。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	case 0x05:
		strErrTip.Format("从机已接受查询,正在进行处理,但需要持续较长的时间。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	case 0x06:
		strErrTip.Format("从机正在处理一个持续时间比较长的指令。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	case 0x07:
		strErrTip.Format("从机不能完成查询中的功能要求。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	case 0x08:
		strErrTip.Format("从机试图阅读扩展存储器,但在存储器中发现奇偶校验错误。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
		break;
	default:
		strErrTip.Format("不可知的错误。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);

	}
	throw(strErrTip);
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: ReceiveByte------接收字符
//----------------------------------------------------
//参数: unsigned char& ch-------------接收到的字符
//----------------------------------------------------
//功能: 接收字符处理
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//  4------没有数据处理
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::ReceiveByte(unsigned char& ch)
{
	if (NULL==m_pComData)
		return 4;			//数据为空
	//--------------------------------------------------
	m_ucRData[m_unNowRLen++]=ch;
	
	if(MODBUS_RTU==m_bFrameMode)
		return ReceiveByte_RTU(ch);
	else	//ASCII
	{
		return ReceiveByte_ASCII(ch);
	}
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Transform------转换成十进制、十六进制、二进制
//----------------------------------------------------
//参数: unsigned char &pChar-------------数据数组
//      unsigned int unLen---------------数据长度
//		unsigned int unType--------------将要转换的类型1:整形;2:十六进制;3:二进制位
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//	NULL	
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//DEL CString CModBus::Transform(const unsigned char* pChar, unsigned int unLen, unsigned int unType)
//DEL {
//DEL 	CString strTxt;
//DEL 	switch(unType)
//DEL 	{
//DEL 		case 1:
//DEL 			{
//DEL 			strTxt.Empty ();
//DEL 			for(unsigned int nIndex=0;nIndex<unLen;nIndex++)
//DEL 				strTxt+=(char*)pChar[nIndex];
//DEL 			break;
//DEL 			}
//DEL 		case 2:
//DEL 			{
//DEL 			strTxt.Empty ();
//DEL 			for(unsigned int nIndex=0;nIndex<unLen;nIndex++)
//DEL 				strTxt+=(char*)pChar[nIndex];
//DEL 			int nNum=atoi(strTxt);
//DEL  			strTxt.Format ("%x",nNum);
//DEL 			strTxt.MakeUpper ();
//DEL 			if(strTxt.GetLength ()==1)
//DEL 			{
//DEL 				strTxt.Insert (0,"0");
//DEL 			}
//DEL 
//DEL 			break;
//DEL 			}
//DEL 		case 3:
//DEL 			{
//DEL 			for(unsigned int i=0;i<unLen;i++)
//DEL 			{
//DEL 				unsigned char ch=*(pChar+i);
//DEL 				for(unsigned int j=0;j<8;j++)
//DEL 				{
//DEL 					bool bBit=((ch>>i & 0x0001)== 0x0001);
//DEL 					if(bBit)
//DEL 						strTxt+="1";
//DEL 					else
//DEL 						strTxt+="0";
//DEL 				}
//DEL 			}
//DEL 			break;
//DEL 			}
//DEL 	}
//DEL 
//DEL 	return strTxt;
//DEL }

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Decoding------译码
//----------------------------------------------------
//参数: CComData& Data-------------数据结构
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//	NULL	
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Decoding(CComData& Data)	//协议译码
{
//
	m_unRLen=0;				//将要接收字符长度
	m_unNowRLen=0;			//已经接收字符长度
//
	if (NULL==&Data)
	{
		m_pComData=NULL;
		return ;		//数据为空
	}
	
	m_pComData=&Data;
	
	if(m_pComData->m_bTranstation && m_pComData->m_bReadWrite)
	{
		return;
	}
	//1、从站地址
	if(m_pComData->m_unStationNum>256)
		throw("ModBus----站号>256");

	//--------------------------------------------------------
	//RTU 模式
	if(MODBUS_RTU==m_bFrameMode)
	{
		//---------------------------------------------------------------------------------
		//     START     | ADDRESS | FUNCTION |   DATA    | CRC CHECK | END
		//---------------------------------------------------------------------------------
		//T1–T2–T3–T4 | 8 BITS  | 8 BITS   |n x 8 BITS | 16 BITS   |T1–T2–T3–T4
		//---------------------------------------------------------------------------------

		Decoding_RTU(Data);
	}
	else	//MODBUS_ASCII
	{
		//---------------------------------------------------------------------------------
		//	START   | ADDRESS | FUNCTION | DATA    | LRC     | CHECK   | END
		//---------------------------------------------------------------------------------
		//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS | 2 CHARS | CRLF
		//---------------------------------------------------------------------------------
	
		Decoding_ASCII(Data);
	}
}


//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_ReadCoils------处理发送字符
//(读取单个/多个线圈DO)  功能代码:0x01
//----------------------------------------------------
//参数: CComData& Data-------------发送数据
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_ReadCoils(CComData& Data)
{
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x01;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8)&0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr&0x00FF;
	
	//4、读写寄存器数量
	unsigned short usCount=(unsigned short) Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	m_pComData->m_ucProtocalTxt[4]=0x00FF & (usCount>>8);
	m_pComData->m_ucProtocalTxt[5]=0x00FF & usCount;


	//5、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code
	//2Byte		Starting Address(0x0000 to 0xFFFF)
	//2Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------
	m_pComData->m_unDataLen=8;	//2(CRC16)

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_ReadDiscreteInputs------处理发送字符
//(读取单个/多个接触器DI)	//功能代码:0x02
//----------------------------------------------------
//参数: CComData& Data-------------发送数据
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_ReadDiscreteInputs(CComData& Data)
{
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x02;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8)&0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr&0x00FF;
	
	//4、读写寄存器数量
	unsigned short usCount=Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	m_pComData->m_ucProtocalTxt[4]=0x00FF & (usCount>>8);
	m_pComData->m_ucProtocalTxt[5]=0x00FF & usCount;


	//5、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code
	//2Byte		Starting Address(0x0000 to 0xFFFF)
	//2Byte		Quantity of Inputs(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------

	m_pComData->m_unDataLen=8;	//2(CRC16)

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_ReadHoldingRegisters------处理发送字符
//(读取单个/多个保持寄存器)		//功能代码:0x03
//----------------------------------------------------
//参数: CComData& Data-------------发送数据
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_ReadHoldingRegisters(CComData& Data)
{
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x03;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8)&0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr & 0x00FF;
	
	//4、读写寄存器数量
	unsigned short usCount=Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	m_pComData->m_ucProtocalTxt[4]=0x00FF & (usCount>>8);
	m_pComData->m_ucProtocalTxt[5]=0x00FF & usCount;


	//5、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code
	//2Byte		Starting Address(0x0000 to 0xFFFF)
	//2Byte		Quantity of Registers(1 to 125(0x7D))
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------
	m_pComData->m_unDataLen=8;	//2(CRC16)

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_ReadInputRegisters------处理接收字符
//(读取单个、多个寄存器)	//功能代码:0x04
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_ReadInputRegisters(CComData& Data)
{
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x04;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8)&0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr & 0x00FF;
	
	//4、读写寄存器数量
	unsigned short usCount=(unsigned short)Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	m_pComData->m_ucProtocalTxt[4]=0x00FF & (usCount>>8);
	m_pComData->m_ucProtocalTxt[5]=0x00FF & usCount;


	//5、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code
	//2Byte		Starting Address(0x0000 to 0xFFFF)
	//2Byte		Quantity of Input Registers(1 to 125(0x7D))
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------

	m_pComData->m_unDataLen=8;	//2(CRC16)

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_WriteSingleCoil------处理接收字符
//(写单个线圈)			//功能代码:0x05
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_WriteSingleCoil(CComData& Data)
{
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x05;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8) & 0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr & 0x00FF;
	
	//4、写入值
	unsigned short usValue=(unsigned short) atoi(Data.m_strRegValue);
	if(usValue==1)
	{	//ON
		m_pComData->m_ucProtocalTxt[4]=0xFF;
		m_pComData->m_ucProtocalTxt[5]=0x00;
	}
	else
	{	//OFF
		m_pComData->m_ucProtocalTxt[4]=0x00;
		m_pComData->m_ucProtocalTxt[5]=0x00;
	}

	//5、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code(0x05)
	//2Byte		Output Address(0x0000 to 0xFFFF)
	//2Byte		Output Value(0x0000 or 0xFF00)
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------

	m_pComData->m_unDataLen=8;	//2(CRC16)

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_WriteSingleRegister------处理接收字符
//(写单个寄存器)	//功能代码:0x06
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_WriteSingleRegister(CComData& Data)
{
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x06;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8) & 0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr & 0x00FF;
	
	//4、写入值-----------注意负数????
	unsigned short usCount=(unsigned short) atoi(Data.m_strRegValue);	//对于整数负数没有问题
	m_pComData->m_ucProtocalTxt[4]=0x00FF & (usCount>>8);
	m_pComData->m_ucProtocalTxt[5]=0x00FF & usCount;

	//5、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code(0x05)
	//2Byte		Register Address(0x0000 to 0xFFFF)
	//2Byte		Register Value(0x0000 or 0xFF00)
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------

	m_pComData->m_unDataLen=8;	

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_WriteMultipleCoils------处理接收字符
//(写多个线圈)	//功能代码:0x0F
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_WriteMultipleCoils(CComData& Data)
{//只支持单个线圈写----调试未成功
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x0F;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8) & 0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr & 0x00FF;
	
	//4、读写寄存器数量
	unsigned short usCount=(unsigned short) Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	m_pComData->m_ucProtocalTxt[4]=0x00FF & (usCount>>8);
	m_pComData->m_ucProtocalTxt[5]=0x00FF & usCount;


	//5、数据字节数
	unsigned int unLen=m_pComData->m_strRegValue.GetLength ();
	unsigned int unMod=unLen%8;
	unsigned int unByteCount=unLen/8+(unMod>0 ? 1:0); 
	m_pComData->m_ucProtocalTxt[6]=unByteCount+1;

	//6、写入值
	int nIndex=6+1;

	m_pComData->m_ucProtocalTxt[nIndex++]=1;
	m_pComData->m_ucProtocalTxt[nIndex++]=0;

/*	m_pComData->m_strRegValue;//存放的是01010101
	for(unsigned int unByte=0;unByte<unByteCount;unByte++)
	{
		char cByte=0x00;
		for(unsinged int unIndex=0;unIndex<8;unIndex++)
		{
			cByte|=
		}
		m_pComData->m_ucProtocalTxt[nIndex++]=ucByte4H<<4 | ucByte4L;
	}
//*/
	//7、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code(0x0F)
	//2Byte		Register Address(0x0000 to 0xFFFF)
	//2Byte		Quantity of Outputs(0x0000 or 0x07B0)
	//1Byte		Byte Count
	//N$ *1 Byte Outputs Value(N$=Quantity of Outputs/8,if then remainder if different of 0=>N=N+1)
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------
	m_pComData->m_unDataLen=7+unByteCount+2+1;
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_WriteMultipleRegisters------处理接收字符(写多个寄存器)	//功能代码:0x10
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_RTU_WriteMultipleRegisters(CComData& Data)	//pass debug 20040213
{//只支持单字
	//1、功能代码
	m_pComData->m_ucProtocalTxt[1]=0x10;

	//2、起始地址
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	m_pComData->m_ucProtocalTxt[2]=(usRegAddr>>8) & 0x00FF;
	m_pComData->m_ucProtocalTxt[3]=usRegAddr & 0x00FF;
	
	//4、写寄存器数量
	unsigned short usCount=(unsigned short) Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	m_pComData->m_ucProtocalTxt[4]=0x00FF & (usCount>>8);
	m_pComData->m_ucProtocalTxt[5]=0x00FF & usCount;

	//5、数据字节数
	m_pComData->m_ucProtocalTxt[6]=2*usCount;
	//6、写入值
	int nIndex=6+1;
//	unsigned short usValue=(unsigned short) atoi(m_pComData->m_strRegValue);	//对于整数负数没有问题
//	m_pComData->m_ucProtocalTxt[nIndex++]=0x00FF & (usValue>>8);
//	m_pComData->m_ucProtocalTxt[nIndex]=0x00FF & usValue;

	m_pComData->m_strRegValue.MakeUpper();
	unsigned int unLen=m_pComData->m_strRegValue .GetLength ();	//存放的是十六进制数

	for(unsigned int unIndex=0;unIndex<unLen;unIndex+=2)
	{
		char cByte[2];
		//
		CString str=m_pComData->m_strRegValue.Mid (unIndex,2);
//		strcpy((LPTSTR)(LPCTSTR)m_pComData->m_strRegValue.Mid (unIndex,2),cByte);
		strcpy(cByte,str);
		unsigned char ucByte4H=(unsigned char)cByte[0];
		unsigned char ucByte4L=(unsigned char)cByte[1];
		if(ucByte4H>=unsigned char('A'))
			ucByte4H-='A';
		else
			ucByte4H-='0';
		if(ucByte4L>='A')
			ucByte4L-='A';
		else
			ucByte4L-='0';
		
		m_pComData->m_ucProtocalTxt[nIndex++]=ucByte4H<<4 | ucByte4L;
	}
//*/
	//7、数据长度
	//---------------------------------------------------------
	//1Byte		站号
	//---------------------------------------------------------
	//1Byte		Function Code(0x10)
	//2Byte		Register Address(0x0000 to 0xFFFF)
	//2Byte		Quantity of Outputs(0x0000 or 0x07B0)
	//1Byte		Byte Count(2*N$)
	//N$ *2 Byte Outputs Value(N$=Quantity of Registers)
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------
	m_pComData->m_unDataLen=7+usCount*2+2;	
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_ReadDiscreteInputs------处理接收字符
//----------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符(读取单个/多个接触器DI)
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_ReadDiscreteInputs(unsigned char &ch)
{	//Read_DI

	if(1==m_unNowRLen-1)		//功能代码
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x02==m_ucRFunctionCode)
		{
			m_unRLen=3+ch+2;	//将要接收字符长度==站号(1)+功能代码(1)+数量(1)+数据(N+1)+校验(2)
			return 0;
		}
		else if(0x82==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x02,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x02,m_pComData->m_unRegAddr);
			return 0;
		}
	}
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{	//数据传输正确
			if(1==m_ucRData[2])	//单个点
//				m_pComData->Transform(&m_ucRData[3],1,true);
				m_pComData->Transform(&m_ucRData[3],1);
			else
				Response_RTU_MVaule(3,m_unRLen-2);			//需要转换
			return 1;
		}
		else
		{	//校验码错误
			Error(ch,0x02,m_pComData->m_unRegAddr);
			return 3;
		}
	}
		
	return 0;
	//---------------------------------------------------------
	//---------------------------------------------------------
	//1Byte		Function Code(0x01)
	//1Byte		Byte count N$
	//nByte		Coil Status (n=N or N+1)[N$=Quantity of Outputs/8,if the remainder is different of 0=>N=N=1;
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_ReadCoils------处理接收字符
//----------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符(读取单个/多个线圈DO)
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_ReadCoils(unsigned char &ch)
{	//Read_DO

	if(1==m_unNowRLen-1)
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x01==m_ucRFunctionCode)
		{
			m_unRLen=3+ch+2; //将要接收字符长度=站号(1)+功能代码(1)+数量(1)+数据(N)+校验(2)
			return 0;
		}
		else if(0x81==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 0;
		}
	}
	//校验码
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;		//校验码[1 High Byte]
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;	//校验码[2 Low  Byte]

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{	//数据传输正确
			if(1==m_ucRData[2])	//单个点
//				m_pComData->Transform(&m_ucRData[3],1,true);
				m_pComData->Transform(&m_ucRData[3],1);
			else
				Response_RTU_MVaule(3,m_unRLen-2);			//需要转换
			return 1;
		}
		else
		{	//校验码错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 3;
		}
	}
		

	return 0;
	//---------------------------------------------------------
	//---------------------------------------------------------
	//1Byte		Function Code(0x01)
	//1Byte		Byte count N$
	//nByte		Coil Status (n=N or N+1)[N$=Quantity of Outputs/8,if the remainder is different of 0=>N=N=1;
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_ReadHoldingRegisters------处理接收字符(读取单个/多个保持寄存器)
//----------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_ReadHoldingRegisters(unsigned char& ch)
{
	if(1==m_unNowRLen-1)		//功能代码
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x03==m_ucRFunctionCode)
		{
			m_unRLen=3+ch+2;	//将要接收字符长度==站号(1)+功能代码(1)+数量(1)+数据(2*N=ch)+校验(2)
			return 0;
		}
		else if(0x83==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x03,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x03,m_pComData->m_unRegAddr);
			return 0;
		}
	}
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{	//数据传输正确
			if(2==m_ucRData[2])	//单个点
//				m_pComData->Transform(&m_ucRData[3],2,true);
				m_pComData->Transform(&m_ucRData[3],2);
			else
				Response_RTU_MVaule(3,m_unRLen-2);			//需要转换
			return 1;
		}
		else
		{	//校验码错误
			Error(ch,0x03,m_pComData->m_unRegAddr);
			return 3;
		}
	}

	return 0;
	//---------------------------------------------------------
	//---------------------------------------------------------
	//1Byte		Function Code(0x01)
	//1Byte		Byte count N$
	//nByte		Coil Status (n=N or N+1)[N$=Quantity of Outputs/8,if the remainder is different of 0=>N=N=1;
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_ReadInputRegisters------处理接收字符(读取单个/多个输入寄存器)
//---------------------------------------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符
//---------------------------------------------------------------------------------
//功能: 对接收到的数据进行译码
//---------------------------------------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_ReadInputRegisters(unsigned char& ch)
{
	if(1==m_unNowRLen-1)		//功能代码
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x04==m_ucRFunctionCode)
		{
			m_unRLen=3+ch+2;	//将要接收字符长度==功能代码(1)+数量(1)+数据(N+1)+校验(2)
			return 0;
		}
		else if(0x84==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x03,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x03,m_pComData->m_unRegAddr);
			return 0;
		}
	}
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{	//数据传输正确
			if(2==m_ucRData[2])	//单个点
//				m_pComData->Transform(&m_ucRData[3],2,true);
				m_pComData->Transform(&m_ucRData[3],2);
			else
			{
				Response_RTU_MVaule(3,m_unRLen-2);			//需要转换
			}
			return 1;
		}
		else
		{	//校验码错误
			Error(ch,0x03,m_pComData->m_unRegAddr);
			return 3;
		}
	}

	return 0;
	//---------------------------------------------------------
	//---------------------------------------------------------
	//1Byte		Function Code(0x01)
	//1Byte		Byte count N$
	//nByte		Coil Status (n=N or N+1)[N$=Quantity of Outputs/8,if the remainder is different of 0=>N=N=1;
	//---------------------------------------------------------
	//2Byte		CRC16
	//---------------------------------------------------------
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_WriteSingleCoil------处理接收字符(写单个线圈)
//----------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_WriteSingleCoil(unsigned char& ch)
{
	if(1==m_unNowRLen-1)
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x05==m_ucRFunctionCode)
		{
			m_unRLen=8;	//将要接收字符长度=站号(1)+功能代码(1)+地址(2)+数据(2)+校验(2)
			return 0;
		}
		else if(0x85==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 0;
		}
	}
	//校验码
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{//接收完毕
			for(unsigned int nIndex=0;nIndex<m_unRLen;nIndex++)
			{
				if(m_ucRData[nIndex]!=m_pComData->m_ucProtocalTxt[nIndex])
					return 3;
			}
			return 1;
		}
	}

	return 0;
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_WriteMultipleCoils------处理接收字符(写多个线圈)
//----------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_WriteSingleRegister(unsigned char& ch)
{
	if(1==m_unNowRLen-1)
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x06==m_ucRFunctionCode)
		{
			m_unRLen=8;	//将要接收字符长度=站号(1)+功能代码(1)+地址(2)+数据(2)+校验(2)
			return 0;
		}
		else if(0x86==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 0;
		}
	}

	//校验码
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{//接收完毕
			for(unsigned int nIndex=0;nIndex<m_unRLen;nIndex++)
			{
				if(m_ucRData[nIndex]!=m_pComData->m_ucProtocalTxt[nIndex])
					return 3;
			}
			return 1;
		}
	}
	return 0;
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_WriteMultipleCoils------处理接收字符(写多个线圈)
//----------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_WriteMultipleCoils(unsigned char& ch)
{
	if(1==m_unNowRLen-1)
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x0F==m_ucRFunctionCode)
		{
			m_unRLen=8;	//将要接收字符长度=功能代码(1)+数量(1)+数据(N+1)+校验(2)
			return 0;
		}
		else if(0x8F==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 0;
		}
	}

	//校验码
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{//接收完毕
			//接收数据错误,要求重发
			for(unsigned int nIndex=2;nIndex<6;nIndex++)
			{
				if(m_ucRData[nIndex]!=m_pComData->m_ucProtocalTxt[nIndex])
					return 2;
			}
			return 1;
		}
	}
	return 0;
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_WriteMultipleRegisters------处理接收字符(写多个寄存器)
//----------------------------------------------------
//参数: unsigned char &ch-------------接收到的字符
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//	0------正在接收记录
//	1------字符接收完毕
//	2------要求重发送一次
//  3------校验错误,要求重发一次
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::Response_RTU_WriteMultipleRegisters(unsigned char& ch)		//通过调试20040221
{	//
	if(1==m_unNowRLen-1)
	{
		m_ucRFunctionCode=ch;
		return 0;
	}
	else if(2==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x10==m_ucRFunctionCode)
		{
			m_unRLen=8;	//将要接收字符长度=站号(1)+功能代码(1)+地址(2)+数量(2)+校验(2)
			return 0;
		}
		else if(0x90==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 0;
		}
	}

	//校验码
	if(m_unNowRLen==m_unRLen-1)	//字符接收完毕
	{
		m_usRCheck=ch;
	}
	else if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck |=ch<<8;

		//进行容余校验
		unsigned short usCheckCRC16=CRC16(&m_ucRData[0],m_unRLen-2);
		if(usCheckCRC16==m_usRCheck)
		{//接收完毕
			//接收数据错误,要求重发
			for(unsigned int nIndex=2;nIndex<6;nIndex++)
			{
				if(m_ucRData[nIndex]!=m_pComData->m_ucProtocalTxt[nIndex])
					return 2;
			}
			return 1;
		}
	}

	return 0;
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Response_RTU_MVaule------处理读取多个数据
//----------------------------------------------------
//参数: int nStart-------------从接收缓冲区的开始位置
//		int nLen---------------接收缓冲区的有效数据长度
//----------------------------------------------------
//功能: 对接收到的数据进行译码,存入数据结构中
//----------------------------------------------------
//返回值:
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Response_RTU_MVaule(int nStart, int nEnd)
{	//十六使用进制ASC码(HexAsc)方式
	m_pComData->m_strRegValue.Empty ();

	for (;nStart<nEnd;nStart++)
	{
		char cT[2];
		char cV=0;
		cT[0]=m_ucRData[nStart]>>4;
		cT[1]=m_ucRData[nStart]&0x0F;
		for(int j=0;j<2;j++)
		{
			if(cT[j]>9)
				cV='A'+cT[j]-0xA;
			else
				cV='0'+cT[j];
			m_pComData->m_strRegValue.Insert (m_pComData->m_strRegValue.GetLength (),cV);
		}						
	}
}

void CModBus::Init()
{
	m_unNowRLen=0;			//已经接收字符长度
	if(m_pComData)
		m_pComData->m_unRcvLen =0;
}

void CModBus::SetFrameMode(BOOL bFrameMode/*=CModBus::MODBUS_RTU*/)
{
	m_bFrameMode=bFrameMode;				//通讯模式:MODBUS_RTU,MODBUS_ASCII
}

BOOL CModBus::GetFrameMode()
{
	return m_bFrameMode;					//通讯模式:MODBUS_RTU,MODBUS_ASCII
}

void CModBus::Decoding_RTU(CComData &Data)
{
	//---------------------------------------------------------------------------------
	//     START     | ADDRESS | FUNCTION |   DATA    | CRC CHECK | END
	//---------------------------------------------------------------------------------
	//T1–T2–T3–T4 | 8 BITS  | 8 BITS   |n x 8 BITS | 16 BITS   |T1–T2–T3–T4
	//---------------------------------------------------------------------------------

	//---------------------------------------------------------
	//1.站号(1Byte)
	//---------------------------------------------------------
	m_pComData->m_ucProtocalTxt[0]=m_pComData->m_unStationNum;

	//---------------------------------------------------------
	//2.Modbus 数据帧
	//---------------------------------------------------------
	//	
	//---------------------------------------------------------
	//---------------------------------------------------------------------------------
	//     START     | ADDRESS | FUNCTION |   DATA    | CRC CHECK | END
	//---------------------------------------------------------------------------------
	//T1–T2–T3–T4 | 8 BITS  | 8 BITS   |n x 8 BITS | 16 BITS   |T1–T2–T3–T4
	//---------------------------------------------------------------------------------
	//2、协议数据单元
	switch(m_pComData->m_unRegType)
	{
		case 1:
		{
			Query_RTU_ReadCoils(Data);
			break;
		}
		case 2:
		{
			Query_RTU_ReadDiscreteInputs(Data);
			break;
		}
		case 3:
		{
			Query_RTU_ReadHoldingRegisters(Data);
			break;
		}
		case 4:
		{
			Query_RTU_ReadInputRegisters(Data);
			break;
		}
		case 5:
		{
			Query_RTU_WriteSingleCoil(Data);
			break;
		}
		case 6:
		{
			Query_RTU_WriteSingleRegister(Data);
			break;
		}
		case 15:
		{
			Query_RTU_WriteMultipleCoils(Data);
			break;
		}
		case 16:
		{
			Query_RTU_WriteMultipleRegisters(Data);
			break;
		}
		default:
		{	//功能代码错误 
				//
			throw("ModBus----功能代码错误");
		}
	}

	//3、进行RCR16校验
	//--------------------------------------------------------
	unsigned short usCRC16;
	/*  //Sample
	m_pComData->m_ucProtocalTxt[0]=0x02;
	m_pComData->m_ucProtocalTxt[1]=0x07;
	usCRC16=CRC16(&m_pComData->m_ucProtocalTxt[0],2);
	//*/

	usCRC16=CRC16(&m_pComData->m_ucProtocalTxt[0],m_pComData->m_unDataLen-2);
	m_pComData->m_ucProtocalTxt[m_pComData->m_unDataLen-1]=(usCRC16>>8)&0x00ff;	//高字节---在后
	m_pComData->m_ucProtocalTxt[m_pComData->m_unDataLen-2]=usCRC16&0x00ff;		//低字节---在前
}


//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Decoding_ASCII------将数据翻译为Modbus ASCII 格式 
//
//----------------------------------------------------
//参数: 
//----------------------------------------------------
//功能: 将数据翻译为Modbus ASCII 通讯格式 
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Decoding_ASCII(CComData &Data)
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA    | LRC     | CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS | 2 CHARS | CRLF
	//---------------------------------------------------------------------------------
	//---------------------------------------------------------
	//1.头(1Byte)---[数据帧Header]
	//---------------------------------------------------------
	m_pComData->m_ucProtocalTxt[0]=(unsigned char)':';

	//---------------------------------------------------------
	//2.站号(2Byte)
	//---------------------------------------------------------

	ToHexAscII((unsigned char)m_pComData->m_unStationNum, m_pComData->m_ucProtocalTxt[1]);

	//---------------------------------------------------------
	//3. Modbus 数据帧
	//---------------------------------------------------------
	//2Byte		Function Code
	//4Byte		Starting Address(0x0000 to 0xFFFF)
	//4Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------

	//协议数据单元
	switch(m_pComData->m_unRegType)
	{
		case 1:
		{
			Query_ASCII_ReadCoils(Data);
			break;
		}
		case 2:
		{
			Query_ASCII_ReadDiscreteInputs(Data);
			break;
		}
		case 3:
		{
			Query_ASCII_ReadHoldingRegisters(Data);
			break;
		}
		case 4:
		{
			Query_ASCII_ReadInputRegisters(Data);
			break;
		}
		case 5:
		{
			Query_ASCII_WriteSingleCoil(Data);
			break;
		}
		case 6:
		{
			Query_ASCII_WriteSingleRegister(Data);
			break;
		}
		case 15:
		{
			Query_ASCII_WriteMultipleCoils(Data);
			break;
		}
		case 16:
		{
			Query_ASCII_WriteMultipleRegisters(Data);
			break;
		}
		default:
		{	//功能代码错误 
				//
			throw("ModBus----功能代码错误");
		}
	}

	//---------------------------------------------------------
	//4.校验 LRC(2Byte)
	//---------------------------------------------------------
	unsigned char ucLRC=LRC(&m_pComData->m_ucProtocalTxt[1], m_pComData->m_unDataLen-5);
	ToHexAscII(ucLRC, m_pComData->m_ucProtocalTxt[m_pComData->m_unDataLen-4]);

	//---------------------------------------------------------
	//5.END-- CR LF(2Byte)
	//---------------------------------------------------------
	m_pComData->m_ucProtocalTxt[m_pComData->m_unDataLen-2]=0x0D;		//CR	回车
	m_pComData->m_ucProtocalTxt[m_pComData->m_unDataLen-1]=0x0A;		//LF	换行
}

/*
int  CModBus::ToHexAscII(unsigned int  unValue,unsigned char &ucBuff)
{
	unsigned char ucByteL=0;
	unsigned char ucByteH=0;
	

	ucByteH=(unsigned char)unValue>>4;
	ucByteL=(unsigned char)unValue & 0x00FF ;

	if(ucByteH>=10)	//0x0A
		ucByteH=ucByteH+'A'-10;
	else
		ucByteH+='0';

	if(ucByteL>=10)	//0x0A
		ucByteL=ucByteL+'A'-10;
	else
		ucByteL+='0';
	
	unsigned char* pucBuff=&ucBuff;
	*pucBuff=ucByteH;
	*(++pucBuff)=ucByteL;

	return 2;
}
//*/

int  CModBus::ToHexAscII(unsigned short usValue,unsigned char &ucBuff)
{
	unsigned char ucByteL=usValue>>8;
	unsigned char ucByteH=usValue & 0x00FF;

	ToHexAscII(ucByteL,ucBuff);

	unsigned char* pucBuff2=&ucBuff+2;
	ToHexAscII(ucByteH,*pucBuff2);

	return 4;
}

int  CModBus::ToHexAscII(unsigned char ucByte,unsigned char &ucBuff)
{
	unsigned char ucByteL=0;
	unsigned char ucByteH=0;

	ucByteH=(unsigned char)ucByte>>4;
	ucByteL=(unsigned char)ucByte & 0x0F ;

	if(ucByteH>=10)	//0x0A
		ucByteH=ucByteH+'A'-10;
	else
		ucByteH+='0';

	if(ucByteL>=10)	//0x0A
		ucByteL=ucByteL+'A'-10;
	else
		ucByteL+='0';
	
	unsigned char* pucBuff=&ucBuff;
	*pucBuff=ucByteH;
	*(++pucBuff)=ucByteL;

	return 2;
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_ASCII_ReadCoils------处理发送字符
//(读取单个/多个线圈DO)  功能代码:0x01
//----------------------------------------------------
//参数: CComData& Data-------------发送数据
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_ReadCoils(CComData& Data)
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA    | LRC CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS     | CR LF
	//---------------------------------------------------------------------------------
	
	//1、功能代码[2 Byte]
	m_pComData->m_ucProtocalTxt[3]='0';
	m_pComData->m_ucProtocalTxt[4]='1';

	//2、起始地址[4 Byte]
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	ToHexAscII(usRegAddr, m_pComData->m_ucProtocalTxt[5]);
	
	//3、读写寄存器数量[2 Byte]
	unsigned short usCount=(unsigned short) Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	ToHexAscII(usCount, m_pComData->m_ucProtocalTxt[9]);


	//4、数据长度
	//---------------------------------------------------------
	//1Byte		头
	//---------------------------------------------------------
	//2Byte		站号
	//---------------------------------------------------------
	//2Byte		Function Code
	//4Byte		Starting Address(0x0000 to 0xFFFF)
	//4Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		LRC
	//---------------------------------------------------------
	//2Byte		END-- CR LF
	//---------------------------------------------------------
	m_pComData->m_unDataLen=17;	//2(LRC)+2(END)
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_ASCII_ReadDiscreteInputs------处理发送字符
//(读取单个/多个接触器DI)	//功能代码:0x02
//----------------------------------------------------
//参数: CComData& Data-------------发送数据
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_ReadDiscreteInputs(CComData& Data)			//功能代码:0x02
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA    | LRC CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS     | CR LF
	//---------------------------------------------------------------------------------

	//1、功能代码[2 Byte]
	m_pComData->m_ucProtocalTxt[3]='0';
	m_pComData->m_ucProtocalTxt[4]='2';

	//2、起始地址[4 Byte]
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	ToHexAscII(usRegAddr, m_pComData->m_ucProtocalTxt[5]);
	
	//3、读写寄存器数量[2 Byte]
	unsigned short usCount=(unsigned short) Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	ToHexAscII(usCount, m_pComData->m_ucProtocalTxt[9]);


	//4、数据长度
	//---------------------------------------------------------
	//2Byte		站号
	//---------------------------------------------------------
	//2Byte		Function Code
	//4Byte		Starting Address(0x0000 to 0xFFFF)
	//4Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		LRC
	//---------------------------------------------------------
	//2Byte		END-- CR LF
	//---------------------------------------------------------
	m_pComData->m_unDataLen=17;	//2(LRC)+2(END)

}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_ASCII_ReadHoldingRegisters------处理发送字符
//(读取单个/多个保持寄存器)		//功能代码:0x03
//----------------------------------------------------
//参数: CComData& Data-------------发送数据
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_ReadHoldingRegisters(CComData& Data)		//功能代码:0x03
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA    | LRC CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS     | CR LF
	//---------------------------------------------------------------------------------

	//1、功能代码[2 Byte]
	m_pComData->m_ucProtocalTxt[3]='0';
	m_pComData->m_ucProtocalTxt[4]='3';

	//2、起始地址[4 Byte]
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	ToHexAscII(usRegAddr, m_pComData->m_ucProtocalTxt[5]);
	
	//3、读写寄存器数量[2 Byte]
	unsigned short usCount=(unsigned short) Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	ToHexAscII(usCount, m_pComData->m_ucProtocalTxt[9]);


	//4、数据长度
	//---------------------------------------------------------
	//2Byte		站号
	//---------------------------------------------------------
	//2Byte		Function Code
	//4Byte		Starting Address(0x0000 to 0xFFFF)
	//4Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		LRC
	//---------------------------------------------------------
	//2Byte		END-- CR LF
	//---------------------------------------------------------
	m_pComData->m_unDataLen=17;	//2(LRC)+2(END)
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_ASCII_ReadInputRegisters------处理接收字符
//(读取单个、多个寄存器)	//功能代码:0x04
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_ReadInputRegisters(CComData& Data)			//功能代码:0x04
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA    | LRC CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS     | CR LF
	//---------------------------------------------------------------------------------

	//1、功能代码[2 Byte]
	m_pComData->m_ucProtocalTxt[3]='0';
	m_pComData->m_ucProtocalTxt[4]='4';

	//2、起始地址[4 Byte]
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	ToHexAscII(usRegAddr, m_pComData->m_ucProtocalTxt[5]);
	
	//3、读写寄存器数量[2 Byte]
	unsigned short usCount=(unsigned short) Data.m_unRegCount;
	if (0==usCount)
		usCount=1;
	ToHexAscII(usCount, m_pComData->m_ucProtocalTxt[9]);


	//4、数据长度
	//---------------------------------------------------------
	//2Byte		站号
	//---------------------------------------------------------
	//2Byte		Function Code
	//4Byte		Starting Address(0x0000 to 0xFFFF)
	//4Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		LRC
	//---------------------------------------------------------
	//2Byte		END-- CR LF
	//---------------------------------------------------------
	m_pComData->m_unDataLen=17;	//2(LRC)+2(END)
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_ASCII_WriteSingleCoil------处理接收字符
//(写单个线圈)			//功能代码:0x05
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_WriteSingleCoil(CComData& Data)				//功能代码:0x05
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA    | LRC CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS     | CR LF
	//---------------------------------------------------------------------------------

	
	//1、功能代码[2 Byte]
	m_pComData->m_ucProtocalTxt[3]='0';
	m_pComData->m_ucProtocalTxt[4]='5';

	//2、起始地址[4 Byte]
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	ToHexAscII(usRegAddr, m_pComData->m_ucProtocalTxt[5]);
	

	//3、写入值[2 Byte]
	unsigned short usValue=(unsigned short) atoi(Data.m_strRegValue);
	if(usValue==1)
	{	//ON
		m_pComData->m_ucProtocalTxt[ 9]='F';
		m_pComData->m_ucProtocalTxt[10]='F';
		m_pComData->m_ucProtocalTxt[11]='0';
		m_pComData->m_ucProtocalTxt[12]='0';
	}
	else
	{	//OFF
		m_pComData->m_ucProtocalTxt[ 9]='0';
		m_pComData->m_ucProtocalTxt[10]='0';
		m_pComData->m_ucProtocalTxt[11]='0';
		m_pComData->m_ucProtocalTxt[12]='0';
	}
	
	
	//4、数据长度
	//---------------------------------------------------------
	//2Byte		站号
	//---------------------------------------------------------
	//2Byte		Function Code
	//4Byte		Starting Address(0x0000 to 0xFFFF)
	//4Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		LRC
	//---------------------------------------------------------
	//2Byte		END-- CR LF
	//---------------------------------------------------------
	m_pComData->m_unDataLen=17;	//2(LRC)+2(END)
	
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_ASCII_WriteSingleRegister------处理接收字符
//(写单个寄存器)	//功能代码:0x06
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_WriteSingleRegister(CComData& Data)			//功能代码:0x06
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA    | LRC CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | n CHARS | 2 CHARS     | CR LF
	//---------------------------------------------------------------------------------

	
	//1、功能代码[2 Byte]
	m_pComData->m_ucProtocalTxt[3]='0';
	m_pComData->m_ucProtocalTxt[4]='6';

	//2、起始地址[4 Byte]
	unsigned short usRegAddr=m_pComData->m_unRegAddr;
	ToHexAscII(usRegAddr, m_pComData->m_ucProtocalTxt[5]);
	

	//3、写入值[2 Byte]
	//整形
	unsigned short usValue=(unsigned short) atoi(Data.m_strRegValue);
	ToHexAscII(usValue, m_pComData->m_ucProtocalTxt[9]);


	//4、数据长度
	//---------------------------------------------------------
	//2Byte		站号
	//---------------------------------------------------------
	//2Byte		Function Code
	//4Byte		Starting Address(0x0000 to 0xFFFF)
	//4Byte		Quantity of coils(1 to 2000(0x7D0))
	//---------------------------------------------------------
	//2Byte		LRC
	//---------------------------------------------------------
	//2Byte		END-- CR LF
	//---------------------------------------------------------
	m_pComData->m_unDataLen=17;	//2(LRC)+2(END)
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_ASCII_WriteMultipleCoils------处理接收字符
//(写多个线圈)	//功能代码:0x0F
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_WriteMultipleCoils(CComData& Data)			//功能代码:0x0F		//十六进制字符串
{	//暂不支持
	throw("ModBus----(写多个线圈)	功能代码:0x0F,不支持");
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Query_RTU_WriteMultipleRegisters------处理接收字符(写多个寄存器)	//功能代码:0x10
//----------------------------------------------------
//参数: CComData& Data-------------发送的数据
//----------------------------------------------------
//功能: 对接收到的数据进行译码
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Query_ASCII_WriteMultipleRegisters(CComData& Data)		//功能代码:0x10		//十六进制字符串
{	//暂不支持
	throw("ModBus----(写多个寄存器)	功能代码:0x10,不支持");
}


int  CModBus::Response_ASCII_ReadCoils(unsigned char& ch)
{
	//---------------------------------------------------------------------------------
	//	START   | ADDRESS | FUNCTION | DATA LEN | DATA    | LRC CHECK   | END
	//---------------------------------------------------------------------------------
	//	1 CHAR: | 2 CHARS | 2 CHARS  | 2 CHARS  | n CHARS | 2 CHARS     | CR LF
	//---------------------------------------------------------------------------------
	//	0		| 1 - 2   | 3 - 4    | 5 - 6    | 6+n     |	            |       
	//---------------------------------------------------------------------------------

	//Read_DO

	if(5==m_unNowRLen-1)	//3-4 byte:功能代码
	{
		m_ucRFunctionCode=(unsigned char)ToHexDec(m_ucRData[3],2);
		return 0;
	}
	else if(7==m_unNowRLen-1)	//已经接收字符长度
	{//接收到的第一个字符
		if(0x01==m_ucRFunctionCode)
		{
			int nRData=ToHexDec(m_ucRData[5],2);
			m_unRLen=7+nRData*2+4; //将要接收字符长度=头(1)+站号(2)+功能代码(2)+数量(2)+数据(N*2)+校验(2)+END(2)
			return 0;
		}
		else if(0x81==m_ucRFunctionCode)
		{//返回错误----Error=0x01 or 0x02 or 0x03 or 0x04
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return ch;
		}
		else
		{//返回错误----功能代号错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 0;
		}
	}
	//校验码
	if(m_unNowRLen==m_unRLen)	//字符接收完毕
	{	
		m_usRCheck=(unsigned short)ToHexDec(m_ucRData[m_unRLen-4],2);	//校验码

		//进行LRC校验
		unsigned short usCheckCRC16=LRC(&m_ucRData[1],m_unRLen-4);
		if(usCheckCRC16==m_usRCheck)
		{	//数据传输正确
			if(1==m_ucRData[2])	//单个点
//				m_pComData->Transform(&m_ucRData[3],1,true);
				m_pComData->Transform(&m_ucRData[3],1);
			else
				Response_RTU_MVaule(3,m_unRLen-2);			//需要转换
			return 1;
		}
		else
		{	//校验码错误
			Error(ch,0x01,m_pComData->m_unRegAddr);
			return 3;
		}
	}
		

	return 0;
	//---------------------------------------------------------
}

int  CModBus::Response_ASCII_ReadDiscreteInputs(unsigned char& ch)
{
	int nReturn=0;

	return nReturn;
}

int  CModBus::Response_ASCII_ReadHoldingRegisters(unsigned char& ch)
{
	int nReturn=0;

	return nReturn;
}

int  CModBus::Response_ASCII_ReadInputRegisters(unsigned char& ch)
{
	int nReturn=0;

	return nReturn;
}

int  CModBus::Response_ASCII_WriteSingleCoil(unsigned char& ch)
{
	int nReturn=0;

	return nReturn;
}

int  CModBus::Response_ASCII_WriteSingleRegister(unsigned char& ch)
{
	int nReturn=0;

	return nReturn;
}

int CModBus::ReceiveByte_RTU(unsigned char& ch)
{
	int nReturn=0;

	//2、协议数据单元
	switch(m_pComData->m_unRegType)
	{
		case 1:
		{
			nReturn=Response_RTU_ReadCoils(ch);
			break;
		}
		case 2:
		{
			nReturn=Response_RTU_ReadDiscreteInputs(ch);
			break;
		}
		case 3:
		{
			nReturn=Response_RTU_ReadHoldingRegisters(ch);
			break;
		}
		case 4:
		{
			nReturn=Response_RTU_ReadInputRegisters(ch);
			break;
		}
		case 5:
		{
			nReturn=Response_RTU_WriteSingleCoil(ch);
			break;
		}
		case 6:
		{
			nReturn=Response_RTU_WriteSingleRegister(ch);
			break;
		}
		case 15:
		{
			nReturn=Response_RTU_WriteMultipleCoils(ch);
			break;
		}
		case 16:
		{
			nReturn=Response_RTU_WriteMultipleRegisters(ch);
			break;
		}
		default:
		{	//功能代码错误 
			break;
				//
		}
	}

	if(0<nReturn)
		m_pComData=NULL;

	return nReturn;
}

int CModBus::ReceiveByte_ASCII(unsigned char& ch)
{
	int nReturn=0;

	//RLen:
	//1		数据帧头:':'
	//2-3	站号
	//
	if(3<=m_unNowRLen)
		return nReturn;


	//2、协议数据单元
	switch(m_pComData->m_unRegType)
	{
		case 1:
		{
			nReturn=Response_ASCII_ReadCoils(ch);
			break;
		}
		case 2:
		{
			nReturn=Response_ASCII_ReadDiscreteInputs(ch);
			break;
		}
		case 3:
		{
			nReturn=Response_ASCII_ReadHoldingRegisters(ch);
			break;
		}
		case 4:
		{
			nReturn=Response_ASCII_ReadInputRegisters(ch);
			break;
		}
		case 5:
		{
			nReturn=Response_ASCII_WriteSingleCoil(ch);
			break;
		}
		case 6:
		{
			nReturn=Response_ASCII_WriteSingleRegister(ch);
			break;
		}
		case 15:
		{
//			nReturn=Response_ASCII_WriteMultipleCoils(ch);
			break;
		}
		case 16:
		{
//			nReturn=Response_ASCII_WriteMultipleRegisters(ch);
			break;
		}
		default:
		{	//功能代码错误 
			break;
				//
		}
	}

	if(0<nReturn)
		m_pComData=NULL;

	return nReturn;
}

long CModBus::ToHexDec(unsigned char &ucBuff,int nLen) const
{
	long nValue=0;

	if(nLen>8)
		return nValue;

	char cBuf[10]; 
	cBuf[nLen]='\0';
	unsigned char * pucVal=NULL;

	for(int n=0;n<nLen;n++)
	{
		pucVal=&ucBuff+n;
		cBuf[n]=*pucVal;
	}

	sscanf(cBuf,"%x",& nValue); 

	return nValue;	
}